# In this example we will demonstrate how to drag and drop a button widget and move it around.

import sys
from PySide import QtGui, QtCore

class Button(QtGui.QPushButton):
    def __init__(self, title, parent):
        super(Button, self).__init__(title, parent)

    # We create a Button class from QPushButton class and re-implement two of its functions, mouseMoveEvent() and
    # mousePressEvent(). The mouseMoveEvent() is the place where the drag and drop operation begins.
    # QtGui.QWidget.mouseMoveEvent(event), For an event 'event', this event handler can be re-implemented in a subclass
    # to receive mouse move events for the widget.
    # QMouseEvent.pos() reports the position of the mouse cursor, relative to its widget.
    def mouseMoveEvent(self, event):
        # QtGui.QMouseEvent.buttons(), Returns the button state when the event was generated. The button state is a
        # combination of Qt.LeftButton , Qt.RightButton , Qt.MidButton using the OR operator.
        if event.buttons() != QtCore.Qt.RightButton:
            return
        # class PySide.QtCore.QMimeData, Constructs a new MIME data object with no data in it.
        mimeData = QtCore.QMimeData()
        # PySide.QtCore.QMimeData objects are usually created using new and supplied to PySide.QtGui.QDrag or
        # PySide.QtGui.QClipboard objects. This is to enable Qt to manage the memory that they use.
        drag = QtGui.QDrag(self)
        # QtGui.QDrag.setMimeData(QtCore.QMimeData), Sets the data to be sent to the given MIME data . Ownership of the
        # data is transferred to the PySide.QtGui.QDrag object.
        drag.setMimeData(mimeData)
        # QtGui.QDrag.setHotSpot(hotspot), hotspot is QtCore.QPoint. Sets the position of the hot spot relative to the
        # top-left corner of the pixmap used to the point specified by hotspot.
        drag.setHotSpot(event.pos() - self.rect().topLeft())
        # QtGui.QDrag.start([supportedActions=Qt.CopyAction]), supportedActions – PySide.QtCore.Qt.DropActions
        # Return type = QtCore.Qt.DropAction
        dropAction = drag.start(QtCore.Qt.MoveAction)

    def mousePressEvent(self, event):
        # QtGui.QWidget.mousePressEvent(event), event is PySide.QtGui.QMouseEvent. This event handler, for event
        # 'event' , can be reimplemented in a subclass to receive mouse press events for the widget.
        QtGui.QPushButton.mousePressEvent(self, event)
        # QtGui.QMouseEvent.button(), Returns the button that caused the event. Note that the returned value is always
        # Qt.NoButton for mouse move events.
        if event.button() == QtCore.Qt.LeftButton:
            print("Press")

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.setAcceptDrops(True)

        self.btn = Button('Button', self)
        self.btn.move(100, 65)

        self.label = QtGui.QLabel("Use Right mouse button to move the Button", self)
        self.label.move(10, 10)

        self.setGeometry(200, 200, 300, 200)
        self.setWindowTitle("Drag and Drop a Button")


    # QtGui.QWidget.dragEnterEvent(event), event is PySide.QtGui.QDragEnterEvent. This event handler is called when a
    # drag is in progress and the mouse enters this widget. The event is passed in the event parameter.
    def dragEnterEvent(self, event):
        event.accept()


    # QtGui.QWidget.dropEvent(event), event is PySide.QtGui.QDropEvent. This event handler is called when the drag is
    # dropped on this widget. The event is passed in the event parameter.
    def dropEvent(self, event):
        # QtGui.QWidget.pos(), Return type:	PySide.QtCore.QPoint. This property holds the position of the widget
        # within its parent widget.
        position = event.pos()
        self.btn.move(position)
        # QtGui.QDropEvent.setDropAction(action), action is QtCore.Qt.DropAction.
        event.setDropAction(QtCore.Qt.MoveAction)
        event.accept()


if __name__ == "__main__":
    appObject = QtGui.QApplication(sys.argv)
    ex = Window()
    ex.show()
    sys.exit(appObject.exec_())
